package geradatawarehouse.dao.abs;

import geradatawarehouse.dao.config.ConnectionConfiguration;
import geradatawarehouse.main.GeraDataWarehouse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Locale;

import javax.naming.ConfigurationException;

public abstract class AbstractDAO {

	public static final String ISO_8859_1_CHARSET = "ISO-8859-1";

	/**
	 * Retorna a consulta SQL do arquivo solicitado
	 * 
	 * @param fileName
	 *            Nome do arquivo dentro do jar
	 * @return Texto da consulta SQL do arquivo.
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	protected static String loadQueryFile(final String fileName)
			throws UnsupportedEncodingException, IOException {
		final InputStreamReader isr = new InputStreamReader(
				GeraDataWarehouse.class.getClassLoader().getResourceAsStream(
						fileName), AbstractDAO.ISO_8859_1_CHARSET);

		final BufferedReader br = new BufferedReader(isr);

		final StringBuilder builder = new StringBuilder();

		String line = br.readLine();

		while (line != null) {
			builder.append(line);
			builder.append("\n");

			line = br.readLine();
		}

		final String query = builder.toString();
		return query;
	}

	protected final ConnectionConfiguration config;

	protected AbstractDAO(
			final ConnectionConfiguration.DatabaseType databaseType)
			throws IOException {
		this.config = ConnectionConfiguration.getInstance(databaseType);
	}

	/**
	 * @return
	 * @throws SQLException
	 */
	protected Connection buildConnection() throws SQLException {
		Connection conn = null;

		try {
			this.loadDriver(this.config.getConnDriverClass());
			conn = DriverManager.getConnection(this.config.getConnString(),
					this.config.getUsername(), this.config.getPassword());
		} catch (ConfigurationException e) {
			throw new SQLException(e);
		} catch (ClassNotFoundException e) {
			throw new SQLException(e);
		}

		return conn;
	}

	/**
	 * @return statement para uma consulta.
	 * @throws SQLException
	 */
	protected Statement buildStatement() throws SQLException {
		final Connection conn = this.buildConnection();
		final Statement smt = conn.createStatement();
		return smt;
	}

	protected String escape(String value) {

		if (value == null) {
			return " ";
		}

		value = value.replace("\\", "\\\\");

		value = value.replace("'", "\\\'");

		return value;
	}

	protected String formatDate(final Date dt) {

		if (dt != null) {
			return DateFormat.getDateInstance(DateFormat.MEDIUM,
					new Locale("en", "US")).format(dt);
		}

		return null;
	}

	/**
	 * Carrega o driver dado.
	 */
	protected void loadDriver(final String driverName)
			throws ClassNotFoundException {
		Class.forName(driverName);
	}

	/**
	 * Retorna um objeto Date a partir de uma String no formato dd/MM/yyyy
	 * 
	 * @param date
	 *            Data em formato dd/MM/yyyy
	 * @return {@link Date} correspondente à String fornecida.
	 */
	protected Date parseDate(final String date) {
		if (date != null) {
			try {
				return DateFormat.getDateInstance(DateFormat.MEDIUM,
						new Locale("pt", "BR")).parse(date);
			} catch (final ParseException e) {
				return null;
			}
		}

		return null;
	}

	protected ResultSet querySelect(final String query) throws SQLException {
		final Statement smt = this.buildStatement();

		return smt.executeQuery(query);
	}
}
